/**
 * 
 */
package edu.wpi.cs509.representation;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.Session;

import edu.wpi.cs509.persistence.HibernateUtil;


/**
 * This class contains a user's game statistics.
 * @author jobeaupr
 *
 */
@Entity
@Table(name = "user_statistics")
public class UserStatistics extends UserName implements Comparable<UserStatistics> {

	/**
	 * serializable version number
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The Statistics ID - this is needed for hibernate
	 */
	@Id
	@Column(name = "id")
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int statsId;
	
	private int gamesWon;
	private int gamesLost;
	private int gamesQuit;
	private int gamesWatched;
	private int wonLeastMoves;
	private int totalPlayTime;
	

	/**
	 * Ratio in DB
	 */
	@Column(name = "ratio")
	@javax.persistence.OrderBy("ratio")
	private float ratio;

	@Column(name = "games_won")
    public int getGamesWon() { return gamesWon; }
	
	@Column(name = "games_lost")
    public int getGamesLost() { return gamesLost; }
	
	@Column(name = "games_quit")
    public int getGamesQuit() { return gamesQuit; }
	
	@Column(name = "games_watched")
    public int getGamesWatched() { return gamesWatched; }
	
	@Column(name = "won_least_moves")
    public int getWonLeastMoves() { return wonLeastMoves; }
	
	@Column(name = "total_play_time")
    public int getTotalPlayTime() { return totalPlayTime; }

	public UserStatistics()
	{
		super();
	}
	
	/**
     * Constructor. Set username.
     * @param userName Sets the userName in the super.
     */
    public UserStatistics(String username) {
    	super(username);
    	this.gamesWon 	   = 0;
    	this.gamesLost 	   = 0;
    	this.gamesQuit 	   = 0;
    	this.gamesWatched  = 0;
    	this.wonLeastMoves = 0;
    	this.totalPlayTime = 0;
    }
    
    public UserStatistics(String username, int playtime) {
    	super(username);
    	this.totalPlayTime = playtime;
    }
    
    /**
     * Increment the total number of games won by a user
     */
    public void incrementGamesWon() {
    	
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.gamesWon++;
		
		//Force a ratio calculation
		getRatio();
		
		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}
    
    /**
     * Increment the total number of games lost by a user
     */
	public void incrementGamesLost() {
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.gamesLost++;
		
		//Force a ratio calculation
		getRatio();

		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}
	
	/**
	 * Increment the total number of games quit for a user
	 */
	public void incrementGamesQuit() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.gamesQuit++;

		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}
	
	/**
	 * Increment the total number of games watched for a user
	 */
	public void incrementGamesWatched() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.gamesWatched++;

		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}
	
	/**
	 * Update a players least number of moves taken to win a game
	 * @param nWonLeastMoves
	 */
	public void setWonLeastMoves(int nWonLeastMoves) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		if ( nWonLeastMoves < this.wonLeastMoves ||
			 0 == this.wonLeastMoves)
		{
			this.wonLeastMoves = nWonLeastMoves;
		}
		
		session.saveOrUpdate(this);
		session.getTransaction().commit();
		
		return;
	}
	
	/**
	 * Increase a users total play time
	 * @param nplayTime - recent game play time, used to increment total time
	 */
	public void incrementTotalPlayTime(int nplayTime) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.totalPlayTime += nplayTime;

		session.saveOrUpdate(this);
		session.getTransaction().commit();
		
		return;
	}

	/**
	 * Forces a calculation of the ratio and returns it.
	 * @return ratio The ratio of wins to games played
	 */
	@Column(name = "ratio")
	public float getRatio() { 
		ratio = (float)this.gamesWon / (this.gamesWon + this.gamesLost);
		
		return this.ratio;
	}
	
	/**
	 * Implement a custom compareTo operator such that comparisons
	 * between two userStatistics objects will be based on win ratios.
	 * 
	 * @param obj should be a UserStatistics
	 * @return ret negative for less than, positive for more than, 0 for equals
	 */
	@Override
	public int compareTo(UserStatistics obj) {
		return Float.compare(getRatio(), obj.getRatio());
	}

	/**
	 * Overriding toString function.
	 */
	public String toString() {
		String ret = "NAME: ["+this.getUsername()+"], Wins: "+this.gamesWon+". Losses: "+this.gamesLost + ".  Ratio: "+this.getRatio();
		
		return ret;
	}
}
